#include "BROKEN_IOCP.h"



BROKEN_IOCP::BROKEN_IOCP()
{
	//Init WinSock2
	if (WSAStartup(MAKEWORD(2, 2), &m_wsaData)) 
	{
		std::cout << "Create WSAStartup() Fail" << std::endl;
		return;
	}

	m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
	m_serverSocket = WSASocketW(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

	if (m_serverSocket == INVALID_SOCKET) {
		closesocket(m_serverSocket);
		WSACleanup();
		std::cout << "Create WSASocketW() Fail" << std::endl;
		return;
	}
}


BROKEN_IOCP::~BROKEN_IOCP()
{
	closesocket(m_serverSocket);
	WSACleanup();
}

BOOL BROKEN_IOCP::BindAndListen(int port)
{
	m_serverAddr.sin_family = AF_INET;
	m_serverAddr.sin_port = htons(static_cast<u_short>(port));
	m_serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	int res = bind(m_serverSocket, (SOCKADDR*)&m_serverAddr, sizeof(SOCKADDR));
	if (res != 0) {
		closesocket(m_serverSocket);
		WSACleanup();
		std::cout << "Create bind() Fail" << std::endl;
		return false;
	}

	res = listen(m_serverSocket, SOMAXCONN);
	if (res != 0) {
		closesocket(m_serverSocket);
		WSACleanup();
		std::cout << "Create bind() Fail" << std::endl;
		return false;
	}
	return true;
}

#if THREAD_TYPE 
void IOCP_WorkThread(BROKEN_IOCP * iocp)
#else
void WINAPI IOCP_WorkThread(BROKEN_IOCP * iocp)
#endif
{
	SHAREIODATA *pshareIOData;
	while (1)
	{
		DWORD dwTrans;
		SHARESOCKETDATA *pshareSocketData;
		BOOL error = GetQueuedCompletionStatus(
			iocp->GetIOCPHandle(), 
			&dwTrans, 
			(LPDWORD)&pshareSocketData, 
			(LPOVERLAPPED*)&pshareIOData,
			WSA_INFINITE
		);

		if (!error) 
		{
			closesocket(pshareSocketData->s);
			delete pshareSocketData;
			delete pshareIOData;
		}

		if (dwTrans == 0) 
		{
			//error
		}
		std::cout << "have msg" << std::endl;

	}
}

#if THREAD_TYPE 
void IOCP_AcceptThread(BROKEN_IOCP * iocp)
#else // 
void WINAPI IOCP_AcceptThread(BROKEN_IOCP *iocp)
#endif
{
	while (1)
	{
		SOCKADDR_IN clientAddr;
		int clientAddrLen = sizeof(clientAddr);

		SOCKET clientSocket = WSAAccept(
			iocp->GetServerSocket(),
			(SOCKADDR*)&clientAddr,
			&clientAddrLen,
			NULL,
			NULL
		);

		if (clientSocket == INVALID_SOCKET) 
		{
			closesocket(clientSocket);
			std::cout << "Accept Client Socket Fail" << std::endl;
		}

		SHARESOCKETDATA *pshareSocketData = new SHARESOCKETDATA;
		ZeroMemory(pshareSocketData, sizeof(SHARESOCKETDATA));//must set 0
		pshareSocketData->s = clientSocket;
		memcpy_s(&pshareSocketData->sAddr, clientAddrLen, &clientAddr, clientAddrLen);

		CreateIoCompletionPort(
			(HANDLE)clientSocket,
			iocp->GetIOCPHandle(), 
			(ULONG_PTR)pshareSocketData, 
			0
		);
		SHAREIODATA *pshareIOData = new SHAREIODATA;  //(SHAREIODATA*)GlobalAlloc(GPTR, sizeof(SHAREIODATA));
		ZeroMemory(pshareIOData, sizeof(SHAREIODATA));
		WSABUF buf;
		buf.buf = pshareIOData->buf;
		buf.len = 2048;
		DWORD dwRecv = 0;
		DWORD dwFlags = 0;
		WSARecv(pshareSocketData->s, &buf, 1, &dwRecv, &dwFlags, &pshareIOData->ol, NULL);
	}
}
